var VOISXml =
{
    indent1 : new String("  "),
    indent2 : new String("    "),
    indent3 : new String("      "),
    newlinejoiner1 : new String("\r\n  "),
    newlinejoiner2 : new String("\r\n    "),
    newlinejoiner3 : new String("\r\n      "),
    andjoiner3 : new String("\r\n      and "),
    orjoiner3 : new String("\r\n      | "),

    StripMarkup : function(value)
    {
        return value.replace(/<[^>]*>/g, "");
    },
    
    EscapeAttribute : function(value)
    {
        // from form to display or database
        value = value.replace(/&/g, "&amp;");
        value = value.replace(/</g, "&lt;");
        value = value.replace(/>/g, "&gt;");
        value = value.replace(/"/g, "&quot;");
        value = value.replace(/'/g, "&apos;");
        return value;
    },
    
    UnescapeAttribute : function(value)
    {
        // from database to form
        value = value.replace(/&amp;/g, "&");
        value = value.replace(/&gt;/g, ">");
        value = value.replace(/&lt;/g, "<");
        value = value.replace(/&quot;/g, "\"");
        value = value.replace(/&apos;/g, "'");
        return value;
    },

    EscapeValue : function(value)
    {
        // from form to display or database
        value = value.replace(/&/g, "&amp;");
        value = value.replace(/</g, "&lt;");
        value = value.replace(/>/g, "&gt;");
        return value;
    },
    
    UnescapeValue : function(value)
    {
        // from database to form
        value = value.replace(/&amp;/g, "&");
        value = value.replace(/&gt;/g, ">");
        value = value.replace(/&lt;/g, "<");
        return value;
    },
    
    DisplayXmlError : false,
	formXmlOutputId : new String("awwwe-browser-vois-wizard-form-xml-output"),

    DisplayXml : function()
    {
        var node = document.getElementById(this.formXmlOutputId);
        var voisMarkup = this.FormToXml();
        if (voisMarkup.length > 0)
        {
            node.value = voisMarkup;
        }
    },

    DisplayXmlToUser : function()
    {
        var voisMarkup = this.FormToXml();
        var node = document.getElementById(VOISEditor.voisMarkupOutputCopyId);
        if (voisMarkup.length == 0)
        {
        	voisMarkup = new String();
        }
        node.value = voisMarkup;
    },

    XmlToForm : function()
    {
        // get the xml doc root element;
        var node = document.getElementById(this.formXmlOutputId);
        if (node == null)
        {
            // this is the first page and the form is not on this page.
            return;
        }
        var voisV = node.value.trim();
        node.value = voisV;
        if (voisV.length == 0)
        {
            // nothing to put in the form
            return;
        }
        if (VOISEditor.formIndex > 0)
        {
            // too dangerous to over write an existing form.
            alert("Can not create a new form from the vois markup until you remove the voice definition sections in the form.");
            return;
        }

        // clear the form
        // this.SectionRemoveAll();

        var parser = new DOMParser();
        var xmlDoc = parser.parseFromString(voisV, "text/xml");
        var vois = xmlDoc.documentElement;
        var node;
        var sayasAt;
        var sayasSay;
        var sayasText;
        
        if (vois.childNodes.length > 0)
        {
            for (var i=0; i<vois.childNodes.length; i++)
            {
                var childNode = vois.childNodes[i];
                if (childNode.nodeType == 1)
                {
                    if (childNode.nodeName == "sayas-at")
                    {
                        sayasSay = childNode.getAttribute("say");
                        sayasAt = this.GetInnerText(childNode);
                        VOISSayas.AddSectionSayasAt(
                            this.UnescapeAttribute(sayasSay),
                            sayasAt
                        );
                    }
                    else if (childNode.nodeName == "sayas-text")
                    {
                        sayasSay = childNode.getAttribute("say");
                        sayasText = this.GetInnerText(childNode);
                        VOISSayas.AddSectionSayasText(
                            this.UnescapeAttribute(sayasSay),
                            sayasText
                        );
                    }
                    else if (childNode.nodeName == "siteurl")
                    {
                        node = document.getElementById(VOISEditor.formSiteURlId);
                        if (node != null)
                        {
                            node.value = this.GetInnerText(childNode);
                        }
                    }
                    else if (childNode.nodeName == "sitename-sayas")
                    {
                        node = document.getElementById(VOISEditor.formSiteNameSayasId);
                        if (node != null)
                        {
                            node.value = this.GetInnerText(childNode);
                        }
                    }
                    else if (childNode.nodeName == "spell-upper-case")
                    {
                        node = document.getElementById(VOISEditor.formSpellUpperCaseId);
                        if (node != null)
                        {
                            node.checked = true;
                        }
                    }
                    else if (
                        childNode.nodeName == "navigation"
                        || childNode.nodeName == "article"
                        || childNode.nodeName == "form"
                    )
                    {
                        this.XmlToForm_TraverseSectionXmlNode(childNode);
                    }
                }
            }
        }
    },

    XmlToForm_TraverseSectionXmlNode : function(node)
    {
    	var i;
        var childNode;
        var typeValue = node.nodeName;
        var descriptionValue = "";
        var conditionValue = "";
        var onlySpeakAtValue = "";
        var neverSpeakAtValue = "";
        var titleAtValue = "";
        var titleValue = "";
        var openWithMovie = "false";
        var isMainContent = "false";
        
        // deal with only speak at text area,
        //  never speak at text area,
        //  title at text,
        //  title text,
        for (i=0; i<node.childNodes.length; i++)
        {
            childNode = node.childNodes[i];
            if (childNode.nodeType == 1)
            {
                // element nodes
                if (
                    childNode.nodeName == "texts-at"
                    || childNode.nodeName == "links-at"
                    || childNode.nodeName == "form-at"
                )
                {
                    onlySpeakAtValue = this.GetInnerText(childNode);
                }
                else if (childNode.nodeName == "condition")
                {
                    conditionValue = this.GetInnerText(childNode);
                }
                else if (childNode.nodeName == "description")
                {
                    descriptionValue = this.GetInnerText(childNode);
                }
                else if (childNode.nodeName == "neverspeak-at")
                {
                    neverSpeakAtValue = this.GetInnerText(childNode);
                }
                else if (childNode.nodeName == "title-at")
                {
                    titleAtValue = this.GetInnerText(childNode);
                }
                else if (childNode.nodeName == "title")
                {
                    titleValue = this.GetInnerText(childNode);
                }
                else if (childNode.nodeName == "open-with-movie")
                {
                    openWithMovie = "true";
                }
                else if (childNode.nodeName == "is-main-content")
                {
                    isMainContent = "true";
                }
            }
        }
        
        this.XmlAddSection(typeValue, descriptionValue, conditionValue, titleValue, titleAtValue, onlySpeakAtValue, neverSpeakAtValue, openWithMovie, isMainContent);
    },
    
    DeepHasInnerText : function(node)
    {
        var i;
        var sayas = node.getAttribute(VOISSayas.sayasAttribute);
        if (sayas == null || sayas.trim().length == 0)
        {
            sayas = node.getAttribute("title");
            if (sayas == null || sayas.trim().length == 0)
            {
                sayas = node.getAttribute("alt");
            }
        }
        var has = (sayas != null && sayas.length > 0);
        if (has == false)
        {
            for (i=0; i<node.childNodes.length; i++)
            {
                var childNode = node.childNodes[i];
                if (childNode.nodeType == 1 && childNode.localName != "script")
                {
                    has = this.DeepHasInnerText(childNode);
                }
                else if (childNode.nodeType == 3 || childNode.nodeType == 4)
                {
                    // text += childNode.data;
                    has = childNode.nodeValue.trim().length > 0;
                }
                if (has)
                {
                    break;
                }
            }
        }
        return has;
    },

    GetInnerText : function(node)
    {
        var i;
        var text = "";
        for (i=0; i<node.childNodes.length; i++)
        {
            var childNode = node.childNodes[i];
            if (childNode.nodeType == 3 || childNode.nodeType == 4)
            {
                // text += childNode.data;
                text += childNode.nodeValue;
            }
        }
        return this.UnescapeValue(text.trim());
    },
    
    ReplaceInnerText : function(node, text)
    {
        for (i=node.childNodes.length-1; i>=0; i--)
        {
            var child = node.childNodes[i];
            if (child.nodeType == 3)
            {
                child.parentNode.removeChild(child);
            }
        }
        tNode = document.createTextNode(this.EscapeValue(text));
        node.appendChild(tNode);
    },
    
    XmlAddSection : function(type, descriptionValue, conditionValue, titleValue, titleAtValue, onlySpeakAtValue, neverSpeakAtValue, openWithMovie, isMainContent)
    {
        if (type == "article")
        {
            VOISEditor.SectionAddNewArtilcleVisualSpace();
        }
        else if (type == "navigation")
        {
            VOISEditor.SectionAddNewNavigationVisualSpace();
        }
        else if (type == "form")
        {
            VOISEditor.SectionAddNewFormVisualSpace();
        }
        // the section has been added
        // now populate it with data
        var i = VOISEditor.formIndex - 1;
        node = document.getElementById(VOISEditor.BuildEnterDescriptionId(i));
        node.value = descriptionValue;
        node = document.getElementById(VOISEditor.BuildConditiontId(i));
        node.value = conditionValue;
        node = document.getElementById(VOISEditor.BuildEnterOnlySpeakAtId(i));
        node.value = onlySpeakAtValue;
        node = document.getElementById(VOISEditor.BuildEnterNeverSpeakAtId(i));
        node.value = neverSpeakAtValue;
        node = document.getElementById(VOISEditor.BuildEnterTitleAtId(i));
        node.value = titleAtValue;
        node = document.getElementById(VOISEditor.BuildEnterTitleId(i));
        node.value = titleValue;

        // articles have the option of starting with a movie
        node = document.getElementById(VOISEditor.BuildOpenWithMovieId(i));
        if (node.options[0].value == openWithMovie)
        {
            node.selectedIndex = 0;
        }
        else
        {
            node.selectedIndex = 1;
        }
        if (type == "article")
        {
            // only show this for articles article
            node.parentNode.style.visibility = "visible";
        }
        else
        {
            node.parentNode.style.visibility = "hidden";
        }

        // is-main-content
        node = document.getElementById(VOISEditor.BuildIsMainContentId(i));
        if (node.options[0].value == isMainContent)
        {
            node.selectedIndex = 0;
        }
        else
        {
            node.selectedIndex = 1;
        }
        //node.parentNode.style.visibility = "visible";
    },

    FormToXml : function()
    {
        var i, j;
        var temp, tempArray1, tempArray2;
        var description, condition, speakOnly, speakNever, openWithMovie, isMainContent;
        var xml;
        var content = [];
        var descriptionValue, onlySpeakAtValue, neverSpeakAtValue, titleAtValue, titleValue, openWithMovieValue, isMainContentValue;
            
        var missingComments = new Number(0);
        var missingTextsAt = new Number(0);
        var missingLinksAt = new Number(0);
        var missingFormAt = new Number(0);
        var missingTitleAndTitleAt = new Number(0);
        var missingMessages = new Array();

        for (i=0; i<VOISEditor.formIndexList.length; i++)
        {
            var tempValue;
            var formId = VOISEditor.formIndexList[i];
            var descriptionNode = document.getElementById(VOISEditor.BuildEnterDescriptionId(formId));
            var conditionNode = document.getElementById(VOISEditor.BuildConditiontId(formId));
            var typeNode = document.getElementById(VOISEditor.BuildSelectTypeId(formId));
            var sectionType = typeNode.value;
            var onlySpeakAtNode = document.getElementById(VOISEditor.BuildEnterOnlySpeakAtId(formId));
            var neverSpeakAtNode = document.getElementById(VOISEditor.BuildEnterNeverSpeakAtId(formId));
            var titleAtNode = document.getElementById(VOISEditor.BuildEnterTitleAtId(formId));
            var titleNode = document.getElementById(VOISEditor.BuildEnterTitleId(formId));
            var openWithMovieNode = document.getElementById(VOISEditor.BuildOpenWithMovieId(formId));
            var isMainContentNode = document.getElementById(VOISEditor.BuildIsMainContentId(formId));

            // clean up white space in condition
            tempValue = conditionNode.value;
            tempValue = this.EscapeValue(tempValue);
            tempArray1 = tempValue.split(/(\s+and\s+)/ig);
            tempArray2 = new Array(0);
            for (j=0; j<tempArray1.length; j+=2)
            {
                temp = tempArray1[j].trim();
                if (temp.length > 0)
                {
                    tempArray2[tempArray2.length] = temp;
                }
            }
            if (tempArray2.length > 0)
            {
                condition = this.indent2 + "<condition>\r\n" + this.indent3 + tempArray2.join(this.andjoiner3) + "\r\n" + this.indent2 + "</condition>\r\n";
            }
            else
            {
                condition = this.indent2 + "<condition></condition>\r\n";;
            }

            // clean up the description
            descriptionValue = descriptionNode.value.trim();
            descriptionValue = this.EscapeValue(descriptionValue);
            tempArray1 = descriptionValue.trim().split("\n");
            tempArray2 = new Array(0);
            for (j=0; j<tempArray1.length; j++)
            {
                temp = tempArray1[j].trim();
                if (temp.length > 0)
                {
                    tempArray2.push(temp);
                }
            }
            if (tempArray2.length > 0)
            {
                description = this.indent2 + "<description>\r\n" + this.indent3 + tempArray2.join(this.newlinejoiner3) + this.newlinejoiner2 + "</description>\r\n";

            }
            else
            {
                description = "";
                missingComments++;
            }

            // clean up white space in only speak at
            tempValue = this.EscapeValue(onlySpeakAtNode.value);
            tempArray1 = tempValue.split(/(\s+\|\s+)/ig);
            tempArray2 = new Array(0);
            for (j=0; j<tempArray1.length; j+=2)
            {
                temp = tempArray1[j].trim();
                if (temp.length > 0)
                {
                    tempArray2.push(temp);
                }
            }
            if (tempArray2.length > 0)
            {
                onlySpeakAtValue = this.newlinejoiner3 + tempArray2.join(this.orjoiner3) + "\r\n";
            }
            else
            {
                onlySpeakAtValue = "";
                if (sectionType == "article")
                {
                    missingTextsAt++;
                }
                else if (sectionType == "navigation")
                {
                    missingLinksAt++;
                }
                else // if (sectionType == "form")
                {
                    missingFormAt++;
                }
            }

            
            // clean up white space in never speak at
            tempValue = this.EscapeValue(neverSpeakAtNode.value);
            tempArray1 = tempValue.split(/(\s+\|\s+)/ig);
            tempArray2 = new Array(0);
            for (j=0; j<tempArray1.length; j+=2)
            {
                temp = tempArray1[j].trim();
                if (temp.length > 0)
                {
                    tempArray2[tempArray2.length] = temp;
                }
            }
            if (tempArray2.length > 0)
            {
                neverSpeakAtValue = this.newlinejoiner3 + tempArray2.join(this.orjoiner3) + "\r\n" + this.indent2;
            }
            else
            {
                neverSpeakAtValue = "";
            }

            // cleean up title at
            titleAtValue = this.EscapeValue(titleAtNode.value.trim());
            if (titleAtValue.length > 0)
            {
                titleAtValue = this.newlinejoiner3 + titleAtValue + this.newlinejoiner2;
            }
            titleValue = this.EscapeValue( this.StripMarkup(titleNode.value.trim()) );
            if (titleValue.length == 0 && titleAtValue.length == 0)
            {
                missingTitleAndTitleAt++;
            }
            
            // is main content
            isMainContentValue = isMainContentNode.options[isMainContentNode.selectedIndex].value;
            isMainContent = (isMainContentValue == "true") ? (this.indent2 + "<is-main-content />\r\n") : ("");

            if (sectionType == "navigation")
            {
                openWithMovie = "";
                speakOnly = this.indent2 + "<links-at>" + onlySpeakAtValue + this.indent2 + "</links-at>\r\n";
                speakNever = this.indent2 + "<neverspeak-at>" + neverSpeakAtValue + "</neverspeak-at>\r\n";
            }
            else if (sectionType == "article")
            {
	            openWithMovieValue = openWithMovieNode.options[openWithMovieNode.selectedIndex].value;
                openWithMovie = (openWithMovieValue == "true") ? (this.indent2 + "<open-with-movie />\r\n") : ("");
                speakOnly = this.indent2 + "<texts-at>" + onlySpeakAtValue + this.indent2 + "</texts-at>\r\n";
                speakNever = this.indent2 + "<neverspeak-at>" + neverSpeakAtValue + "</neverspeak-at>\r\n";
            }
            else
            {
                // form
                openWithMovie = "";
                speakOnly = this.indent2 + "<form-at>" + onlySpeakAtValue + this.indent2 + "</form-at>\r\n";
                speakNever = "";
            }
            xml = "  <" + sectionType + ">\r\n" + isMainContent + openWithMovie
                + description
                + condition
                + this.indent2 + "<title>" + titleValue + "</title>\r\n"
                + this.indent2 + "<title-at>" + titleAtValue + "</title-at>\r\n"
                + speakOnly
                + speakNever
                + "  </" + sectionType + ">\r\n";
            content.push(xml);
        }
        xml = "";
        for (i=0; i<content.length; i++)
        {
            xml += "\r\n"
                + content[i]
                + "\r\n";
        }
        // site url and name sayas
        var siteUrlNode = document.getElementById(VOISEditor.formSiteURlId);
        var siteUrl;
        if (siteUrlNode != null)
        {
            siteUrl = this.EscapeValue(siteUrlNode.value.trim());
        }
        else
        {
            siteUrl = "";
        }
        var siteNameNode = document.getElementById(VOISEditor.formSiteNameSayasId);
        var siteName;
        if (siteNameNode != null)
        {
            siteName = this.EscapeValue(siteNameNode.value.trim());
        }
        else
        {
            siteName = "";
        }
        // Spell Upper Case
        var spellUpperCaseNode = document.getElementById(VOISEditor.formSpellUpperCaseId);
        var spellUpperCase;
        if (spellUpperCaseNode != null && spellUpperCaseNode.checked == true)
        {
            spellUpperCase = "  <spell-upper-case />\r\n";
        }
        else
        {
            spellUpperCase = "";
        }

        if (
            siteUrl.length > 0
            && siteName.length > 0
            && content.length > 0
            && (missingComments + missingTextsAt + missingLinksAt + missingFormAt + missingTitleAndTitleAt == 0)
        )
        {
            this.DisplayXmlError = false;
            return(
                "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n"
                + "<vois>\r\n\r\n"
                + "  <siteurl>" + siteUrl + "</siteurl>\r\n"
                + "  <sitename-sayas>" + siteName + "</sitename-sayas>\r\n"
                + spellUpperCase
                + this.FormToXmlSayas()
                + xml
                + "\r\n</vois>\r\n"
            );
        }
        else
        {
            // build missing message
            if (siteName.length == 0)
            {
                missingMessages[missingMessages.length] = "\"Say Site Name As\" is the missing.";
            }
            if (siteUrl.length == 0)
            {
                missingMessages[missingMessages.length] = "\"Site URL\" is the missing.";
            }
            if (content.length == 0)
            {
                missingMessages[missingMessages.length] = "You have not defined any visual spaces on the \"Visual Spaces\" page.";
            }
            if (missingComments == 1)
            {
                missingMessages[missingMessages.length] = "1 visual space definition is the missing \"Description\" on the \"Visual Spaces\" page.";
            }
            else if (missingComments > 1)
            {
                missingMessages[missingMessages.length] = missingComments.toString() + " visual space definitions are missing \"Description\" on the \"Visual Spaces\" page.";
            }
            if (missingTextsAt == 1)
            {
                missingMessages[missingMessages.length] = "1 visual space definition is missing \"Texts At\" on the \"Visual Spaces\" page.";
            }
            else if (missingTextsAt > 1)
            {
                missingMessages[missingMessages.length] = missingOnlySpeakAt.toString() + " visual space definitions are missing \"Texts At\" on the \"Visual Spaces\" page.";
            }
            if (missingLinksAt == 1)
            {
                missingMessages[missingMessages.length] = "1 visual space definition is missing \"Links At\" on the \"Visual Spaces\" page.";
            }
            else if (missingLinksAt > 1)
            {
                missingMessages[missingMessages.length] = missingOnlySpeakAt.toString() + " visual space definitions are missing \"Links At\" on the \"Visual Spaces\" page.";
            }
            if (missingFormAt == 1)
            {
                missingMessages[missingMessages.length] = "1 visual space definition is missing \"Form At\" on the \"Visual Spaces\" page.";
            }
            else if (missingFormAt > 1)
            {
                missingMessages[missingMessages.length] = missingOnlySpeakAt.toString() + " visual space definitions are missing \"Form At\" on the \"Visual Spaces\" page.";
            }
            if (missingTitleAndTitleAt == 1)
            {
                missingMessages[missingMessages.length] = "1 visual space definition is missing both \"Title At\" and \"Title\" on the \"Visual Spaces\" page.";
            }
            else if (missingTitleAndTitleAt > 1)
            {
                missingMessages[missingMessages.length] = missingTitleAndTitleAt.toString() + " visual space definitions are missing both \"Title At\" and \"Title\" on the \"Visual Spaces\" page.";
            }
            alert(
                missingMessages.join("\r\n")
            );
            this.DisplayXmlError = true;
            return "";
        }
    },
    
    FormToXmlSayas : function ()
    {
        // form to xml
        var xml = new Array();
        var i;
        var divId;
        var sayasId;
        var atId;
        var sayasNode;
        var atNode;
        for (i=0; i<VOISSayas.currentSayasTextId; i++)
        {
            divId = VOISSayas._BuildSayasTextDivId(i);
            sayasId = VOISSayas.BuildSayasTextSayasId(divId);
            atId = VOISSayas.BuildSayasTextAtId(divId);
            sayasNode = document.getElementById(sayasId);
            atNode = document.getElementById(atId);
            if (atNode != null && atNode.value.length > 0)
            {
                if (sayasNode != null)
                {
                    xml[xml.length] =
                        "  <sayas-text say=\"" + this.EscapeAttribute(sayasNode.value.trim()) + "\">"
                        + this.EscapeValue(atNode.value.trim())
                        + "</sayas-text>";
                }
            }
        }
        for (i=0; i<VOISSayas.currentSayasAtId; i++)
        {
            divId = VOISSayas._BuildSayasAtDivId(i);
            sayasId = VOISSayas.BuildSayasAtSayasId(divId);
            atId = VOISSayas.BuildSayasAtAtId(divId);
            sayasNode = document.getElementById(sayasId);
            atNode = document.getElementById(atId);
            if (atNode != null && atNode.value.length > 0)
            {
                if (sayasNode != null)
                {
                    xml[xml.length] =
                        "  <sayas-at say=\"" + this.EscapeAttribute(sayasNode.value.trim()) + "\">"
                        + this.EscapeValue(atNode.value.trim())
                        + "</sayas-at>";
                }
            }
        }
        return "\r\n" + xml.join("\r\n") + "\r\n";
    }
}